﻿using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using mozhi.smarterp.AuthorCenter.Enums;
using mozhi.smarterp.AuthorCenter.Users.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TenantManagement;
using Volo.Abp.Users;

namespace mozhi.smarterp.AuthorCenter.Users
{
    public class UserTenantAppService : AuthorCenterAppService, IUserTenantAppService
    {
        private IUserTenantRepository _repository;

        private ITenantRepository _tenantRepository;

        protected IdentityUserManager _userManager { get; }

        private ICurrentTenant _currentTenant { get; }

        private IIdentityUserRepository _userRepository { get; }

        private IGuidGenerator _guidGenerator;

        public UserTenantAppService(IUserTenantRepository repository, ITenantRepository tenantRepository, IdentityUserManager userManager ,
            ICurrentTenant currentTenant , IIdentityUserRepository userRepository , IGuidGenerator guidGenerator)
        {
            _repository = repository;
            _tenantRepository = tenantRepository;
            _userManager = userManager;
            _currentTenant = currentTenant;
            _userRepository = userRepository;
            _guidGenerator = guidGenerator;
        }

        public async Task<List<UserTenantDto>> UpdateAsync(UserTenantUpdateDto input)
        {
            //企业用户，不带租户Id
            var user = await _userManager.GetByIdAsync(input.UserId);

            if (user == null)
                throw new BusinessException("100000", $"用户:{input.UserId}不存在");

            if (input.TenantIds == null || input.TenantIds.Count == 0)
                throw new BusinessException("100000", "租户为空");

            var dtos = new List<UserTenantDto>();

            foreach(var tenantId in input.TenantIds)
            {
                IdentityUser userInTenant = null;

                using (_currentTenant.Change(tenantId))
                {
                    userInTenant = (await _userRepository.GetListAsync(null, 1, 0, null, false, null, null, null, null, user.Email)).FirstOrDefault();

                    if (userInTenant == null)
                    {
                        //新增一个租户的用户
                        userInTenant = new IdentityUser(_guidGenerator.Create(), user.UserName, user.Email, tenantId);
                        userInTenant.ExtraProperties.Add("UserType", (int)UserType.EnterpriseAdmin);

                        await _userRepository.InsertAsync(userInTenant, true);
                    }
                }

                using (_currentTenant.Change(null))
                {
                    var entity = new UserTenant(tenantId, input.UserId, userInTenant.Id);

                    await _repository.InsertAsync(entity);

                    var dto = ObjectMapper.Map<UserTenant, UserTenantDto>(entity);

                    dtos.Add(dto);
                }
            }


            await LoadUserTenantAsync(dtos);

            return dtos;

        }

        public async Task DeleteAsync(Guid id)
        {
            await _repository.DeleteAsync(id);
        }

        public async Task<UserTenantDto> GetAsync(Guid id)
        {
            var entity = await _repository.GetAsync(id);

            var dto = ObjectMapper.Map<UserTenant, UserTenantDto>(entity);

            await LoadUserTenantAsync(new List<UserTenantDto> { dto });

            return dto;
        }

        public async Task<UserTenantDto> GetAsync(Guid userId , Guid tenantId)
        {
            var entity = await _repository.FindAsync(userId , tenantId);

            var dto = ObjectMapper.Map<UserTenant, UserTenantDto>(entity);

            await LoadUserTenantAsync(new List<UserTenantDto> { dto });

            return dto;
        }

        public async Task<PagedResultDto<UserTenantDto>> GetListAsync(UserTenantFilter filter)
        {
            var count = await _repository.GetCountAsync(filter.UserId, filter.TenantId);

            var items = await _repository.GetListAsync(null, filter.MaxResultCount, filter.SkipCount, filter.UserId, filter.TenantId);

            var dtos = ObjectMapper.Map<List<UserTenant>, List<UserTenantDto>>(items);

            await LoadUserTenantAsync(dtos);

            return new PagedResultDto<UserTenantDto>()
            {
                TotalCount = count,
                Items = dtos
            };
        }

        public async Task<string> GenerateUserTenantLoginToken(UserTenantSwitchDto input)
        {
            var user = await _userManager.GetByIdAsync(input.SourceLinkUserId);

            if (user == null)
                throw new BusinessException($"用户:{input.SourceLinkUserId}不存在");

            //如果SourceLinkTenantId不为空，表示的是租户信息，需要用租户的userId 查主用户的Id

            var userTenant = input.SourceLinkTenantId.HasValue ? await _repository.FindAsync(default, input.SourceLinkTenantId.Value, input.SourceLinkUserId)
                : await _repository.FindAsync(input.SourceLinkUserId, input.TargetLinkTenantId.Value);

            if (userTenant == null)
                throw new BusinessException($"用户：{input.SourceLinkUserId}没有关联用户信息");

            using (CurrentTenant.Change(input.TargetLinkTenantId))
            {
                IdentityUser targetUser = await _userManager.GetByIdAsync(input.TargetLinkUserId);

                if (targetUser == null)
                    throw new BusinessException($"用户不存在：{input.TargetLinkUserId}");

                var token = await _userManager.GenerateUserTokenAsync(targetUser, "LinkLoginProvider",
                    "linklogin-auth");

                return token;
            }
        }

        public async Task<bool> VerifyUserTenantLoginTokenAsync(string userId , Guid? tenantId , string token)
        {
            using (CurrentTenant.Change(tenantId))
            {
                var user = await _userManager.FindByIdAsync(userId);

                var isValid = await _userManager.VerifyUserTokenAsync(user, "LinkLoginProvider", "linklogin-auth", token);
               

                return isValid;
            }

        }

        public async Task<UserTenantDto> GetCurrentAsync()
        {
            var userId = CurrentUser.Id;

            var tenantId = CurrentUser.TenantId;

            UserTenant userTenant = await _repository.FindAsync(default, tenantId.Value, userId);

            var dto = ObjectMapper.Map<UserTenant, UserTenantDto>(userTenant);

            return dto;
        }

        #region
        private async Task LoadUserTenantAsync(List<UserTenantDto> dtos)
        {
           foreach(var dto in dtos)
            {
                var user = await _userManager.GetByIdAsync(dto.UserId);

                var tenant = await _tenantRepository.FindAsync(dto.TenantId);

                dto.UserName = user?.UserName;
                dto.TenantName = tenant?.Name;
            }
        }
        #endregion
    }
}
